#include <thread>
#include <vector>
#include <atomic>
#include <cstddef>
#include <iostream>
#include <functional>
#include <stdexcept>

using consumer = std::function<void()>;
using producer = std::function<void()>;

template <typename... Args> void print(const Args &...args)
{
    ((std::cout << args << " "), ...);
    std::cout << std::endl;
}

// 这个无锁队列是非线程安全的,所以测试是无法通过的
template <typename T> class UnlockQueue
{
public:
    UnlockQueue(std::size_t size) : _ring_queue(size), _head(0), _tail(0) {}

    void enqueue(const T &val)
    {
        // 获取当前队尾
        std::size_t currentTail = _tail.load();
        // 比较是否处于队尾
        std::size_t nextTail = (currentTail + 1) % _ring_queue.size();
        if (nextTail == _head.load())
        {
            throw std::overflow_error("Queue is full");
        }
        // 进行原子的push
        _ring_queue[currentTail] = val;
        // 让其他线程可见
        _tail.store(nextTail, std::memory_order_release);
    }

    T dequeue()
    {
        std::size_t currentHead = _head.load();
        if (currentHead == _tail.load())
        {
            throw std::overflow_error("Queue is empty");
        }
        std::size_t nextHead = (currentHead + 1) % _ring_queue.size();
        T val = _ring_queue[currentHead];
        _head.store(nextHead);
        return val;
    }

private:
    std::vector<T> _ring_queue;
    // 获取当前头尾的位置
    std::atomic<std::size_t> _head;
    std::atomic<std::size_t> _tail;
};

// ... existing code ...

// --- Test Code for the Unsafe Queue ---

// Global instance of the problematic queue
UnlockQueue<int> unsafe_queue(100);

// Atomics for tracking results
std::atomic<long long> consumed_sum = 0;
std::atomic<int> consumed_count = 0;
std::atomic<int> producer_errors = 0; // Count enqueue errors
std::atomic<bool> producers_finished = false;

// Producer task for the unsafe queue
void unsafe_produce(int items_to_produce)
{
    for (int i = 1; i <= items_to_produce; ++i)
    {
        bool enqueued = false;
        while (!enqueued)
        {
            try
            {
                unsafe_queue.enqueue(i);
                enqueued = true;
            }
            catch (const std::overflow_error &)
            {
                // Queue is full, let other threads run and try again
                producer_errors++;
                std::this_thread::yield();
            }
        }
    }
}

// Consumer task for the unsafe queue
void unsafe_consume()
{
    while (!producers_finished.load() || consumed_count.load() < 20000)
    {
        try
        {
            int val = unsafe_queue.dequeue();
            consumed_sum += val;
            consumed_count++;
        }
        catch (const std::overflow_error &)
        {
            // Queue is empty, let other threads run
            if (producers_finished.load())
            {
                // If producers are done and queue is empty, we might be done
                // But due to race conditions, we might need to check again
            }
            std::this_thread::yield();
        }
    }
}

void run_test()
{
    const int num_producers = 2;
    const int num_consumers = 2;
    const int items_per_producer = 10000;
    const int total_items = num_producers * items_per_producer;

    print("--- Starting Test for the Unsafe UnlockQueue ---");
    print("This test is expected to FAIL to demonstrate the race condition.");

    std::vector<std::thread> producers;
    std::vector<std::thread> consumers;

    // Start consumers
    for (int i = 0; i < num_consumers; ++i)
    {
        consumers.emplace_back(unsafe_consume);
    }

    // Start producers
    for (int i = 0; i < num_producers; ++i)
    {
        producers.emplace_back(unsafe_produce, items_per_producer);
    }

    // Wait for all producers to finish
    for (auto &p : producers)
    {
        p.join();
    }

    producers_finished.store(true);
    print("\n--- Producers finished ---");

    // Wait for all consumers to finish
    for (auto &c : consumers)
    {
        c.join();
    }
    print("--- Consumers finished ---");

    // --- Verification ---
    print("\n--- Verification ---");
    // The sum of an arithmetic sequence from 1 to N is N * (N + 1) / 2
    long long expected_sum_per_producer =
        (long long)items_per_producer * (items_per_producer + 1) / 2;
    long long expected_sum = expected_sum_per_producer * num_producers;

    print("Total items that should have been produced:", total_items);
    print("Total items actually consumed:", consumed_count.load());
    print("Enqueue retries (due to full queue):", producer_errors.load());
    print("Expected sum of all items:", expected_sum);
    print("Actual sum of consumed items:", consumed_sum.load());

    if (consumed_count.load() == total_items &&
        consumed_sum.load() == expected_sum)
    {
        print("\n[UNEXPECTED SUCCESS] The test passed. Try running again, "
              "failure is likely.");
    }
    else
    {
        print("\n[EXPECTED FAILURE] The test failed as predicted. Data was "
              "lost or corrupted due to the race condition.");
    }
}

std::atomic<int> a_int;
int test_val = 4;
int target_val = 5;
bool exchange = false;

void p()
{
    print("a_int = ", a_int, "test_val = ", test_val,
          "target_val = ", target_val, "exchange = ", exchange);
}
int main()
{
    // run_test();
    a_int = 10;
    p();

    // a_int != test_val false,test_val = a_int
    // exchange = a_int.compare_exchange_strong(test_val, target_val);
    exchange = a_int.compare_exchange_weak(test_val, target_val);
    p();

    // a_int == test_val, true, a_int = target_val
    // exchange = a_int.compare_exchange_strong(test_val, target_val);
    exchange = a_int.compare_exchange_weak(test_val, target_val);
    p();

    return 0;
}